/**
 * 
 * Copyright (C) 2011 Cody Stoutenburg . All rights reserved.
 *
 *       This program is free software; you can redistribute it and/or
 *       modify it under the terms of the GNU Lesser General Public License
 *       as published by the Free Software Foundation; either version 2.1
 *       of the License, or (at your option) any later version.
 *
 *       This program is distributed in the hope that it will be useful,
 *       but WITHOUT ANY WARRANTY; without even the implied warranty of
 *       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *       GNU Lesser General Public License for more details.
 *
 *       You should have received a copy of the GNU Lesser General Public License
 *       along with this program; if not, write to the Free Software
 *       Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
 * 
 */
package ca.usherbrooke.world.representation;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.newdawn.slick.geom.Rectangle;

import ca.usherbrooke.model.bridge.IEntityModelObject;
import ca.usherbrooke.model.bridge.IEquipmentModelObject;
import ca.usherbrooke.model.entity.IEntityModel;
import ca.usherbrooke.model.equipment.EquipmentModel;
import ca.usherbrooke.model.feature.FeatureModel;
import ca.usherbrooke.model.world.BasicWorldModel;
import ca.usherbrooke.model.world.IWorldModel;
import ca.usherbrooke.tools.position.Vector2D;

/**
 * @author Cody Stoutenburg
 * 
 */
public class SimpleWorld extends BasicWorldModel implements IWorldModel {
	private static final long serialVersionUID = 1L;

	private final List<EquipmentModel> allEquipments;

	public SimpleWorld(IWorldModel world) {
		super(32, 0, 0, 0, 0);

		allGrounds = new FeatureModel[1][1];
		allEquipments = new ArrayList<EquipmentModel>();
		this.mergeWorld(world);
	}

	public void mergeWorld(IWorldModel world) {
		int xMax = world.getTileWidth();
		int yMax = world.getTileHeight();
		if (allGrounds.length > 0) {
			xMax = Math.max(xMax, allGrounds.length);
			yMax = Math.max(yMax, allGrounds[0].length);
		}

		if (allGrounds.length < xMax || allGrounds[0].length < yMax) {
			// copy all elements
			FeatureModel[][] copy = new FeatureModel[allGrounds.length][allGrounds[0].length];
			for (int i = 0; i < allGrounds.length; ++i) {
				for (int j = 0; j < allGrounds[0].length; ++j) {
					copy[i][j] = allGrounds[i][j];
				}
			}

			allGrounds = new FeatureModel[xMax][yMax];
			for (int i = 0; i < copy.length; ++i) {
				for (int j = 0; j < copy[0].length; ++j) {
					allGrounds[i][j] = copy[i][j];
				}
			}
		}

		for (int i = 0; i < world.getTileWidth(); ++i) {
			for (int j = 0; j < world.getTileHeight(); ++j) {
				FeatureModel feature = world.getTileAt(i, j);
				if (feature != null) {
					allGrounds[i][j] = feature;
				}
			}
		}

		this.realTimeElapse = world.getRealTimeElapse();

		List<EquipmentModel> allNewEquipment = world.getAllEquipments();
		for (EquipmentModel eq : allNewEquipment) {
			if (this.allEquipments.contains(eq)) {
				this.allEquipments.remove(eq);
				this.allEquipments.add(eq);
			}
		}

		Rectangle worldSize = world.getSize();
		float width = worldSize.getMinX() + worldSize.getWidth();
		float height = worldSize.getMinY() + worldSize.getHeight();

		if (width > getWidth()) {
			size.setWidth(width);
		}
		if (height > getHeight()) {
			size.setHeight(height);
		}

		/*
		System.out.println("Simple world:");
		for (int i = 0; i < getTileWidth(); ++i) {
			for (int j = 0; j < getTileHeight(); j++) {
				if (getTileAt(i, j) instanceof WallModel) {
					System.out.print("X");
				} else if (getTileAt(i, j) == null) {
					System.out.println("U");
				} else {
					System.out.print("O");
				}
			}
			System.out.println();
		}
		System.out.println("------------------------");
		*/
	}

	// /////////////// NOT IMPLEMENTED METHODS //////////////////

	@Override
	public IEntityModel getEntity(Long guid) {
		return null;
	}

	@Override
	public IEntityModel getEntity(Vector2D position) {
		return null;
	}

	@Override
	public List<IEntityModel> getAllEntities() {
		return Collections.emptyList();
	}

	@Override
	public List<IEntityModel> getEntities(Rectangle position) {
		return Collections.emptyList();
	}

	@Override
	public void update(int delta) {
		throw new UnsupportedOperationException("Method not implemented");
	}

	@Override
	public IWorldModel getVision(Long guid) {
		throw new UnsupportedOperationException("Method not implemented");
	}

	@Override
	public EquipmentModel createEquipment(IEquipmentModelObject equipement) {
		throw new UnsupportedOperationException("Method not implemented");
	}

	@Override
	public IEntityModel createEntity(IEntityModelObject entity) {
		throw new UnsupportedOperationException("Method not implemented");
	}

	@Override
	public IWorldModel copyToTransfert() {
		throw new UnsupportedOperationException("Method not implemented");
	}

	@Override
	public List<EquipmentModel> getEquipment(Vector2D position) {
		List<EquipmentModel> result = new ArrayList<EquipmentModel>();
		for (EquipmentModel equipments : allEquipments) {
			if (equipments.getSize().contains(position.getX().floatValue(),
					position.getY().floatValue())) {
				result.add(equipments);
			}
		}
		return result;
	}

	@Override
	public List<EquipmentModel> getEquipment(Rectangle position) {
		List<EquipmentModel> result = new ArrayList<EquipmentModel>();
		for (EquipmentModel equipments : allEquipments) {
			if (equipments.getSize().contains(position)
					|| equipments.getSize().intersects(position)) {
				result.add(equipments);
			}
		}
		return result;
	}

	@Override
	public EquipmentModel getEquipment(Long guid) {
		EquipmentModel result = null;
		for (EquipmentModel equipments : allEquipments) {
			if (equipments != null && equipments.getGuid().equals(guid)) {
				result = equipments;
				break;
			}
		}
		return result;
	}

	@Override
	public List<EquipmentModel> getAllEquipments() {
		return allEquipments;
	}
}
